using System;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Volo.Abp;
using Volo.Abp.AspNetCore;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AutoMapper;
using Volo.Abp.Caching;
using Volo.Abp.Http.Client;
using Volo.Abp.Modularity;
using Volo.Abp.Threading;
using Matrix.ServiceCommunication.Services;
using Matrix.ServiceCommunication.Discovery;
using Matrix.ServiceCommunication.Authentication;
using Matrix.ServiceCommunication.Resilience;
using Matrix.ServiceCommunication.Monitoring;
using Matrix.ServiceCommunication.Options;

namespace Matrix.ServiceCommunication
{
    /// <summary>
    /// Matrix.ServiceCommunication模块
    /// 轻量级服务通信SDK
    /// </summary>
    [DependsOn(
        typeof(AbpAspNetCoreModule),
        typeof(AbpAspNetCoreMvcModule),
        typeof(AbpHttpClientModule),
        typeof(AbpCachingModule),
        typeof(AbpAutoMapperModule)
    )]
    public class MatrixServiceCommunicationModule : AbpModule
    {
        public override void PreConfigureServices(ServiceConfigurationContext context)
        {
            // 配置AutoMapper
            PreConfigure<IMapperBuilderExpression>(config =>
            {
                config.AddProfile<ServiceCommunicationAutoMapperProfile>();
            });

            // 配置动态HTTP客户端代理
            PreConfigure<AbpHttpClientBuilderOptions>(options =>
            {
                options.ProxyClientActions.Add((clientBuilder, name) =>
                {
                    // 为服务通信客户端添加默认配置
                    clientBuilder.ConfigureHttpClient(client =>
                    {
                        client.Timeout = TimeSpan.FromSeconds(30);
                        client.DefaultRequestHeaders.Add("User-Agent", "Matrix.ServiceCommunication/2.0");
                    });
                });
            });
        }

        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var services = context.Services;
            var configuration = context.Services.GetConfiguration();

            // 配置选项
            services.AddOptions<ServiceCommunicationOptions>()
                .Bind(configuration.GetSection("Matrix:ServiceCommunication"))
                .ValidateDataAnnotations();

            // 注册核心服务
            services.AddTransient<IMatrixServiceClient, MatrixServiceClient>();
            services.AddTransient<IServiceClientFactory, ServiceClientFactory>();
            services.AddTransient<IServiceDiscoveryProvider, MatrixServiceDiscoveryProvider>();
            services.AddTransient<IServiceCommunicationMetrics, ServiceCommunicationMetrics>();

            // 注册认证提供者
            services.AddTransient<IAuthenticationProvider, HybridAuthenticationProvider>();

            // 注册弹性策略提供者
            services.AddTransient<IResilienceStrategyProvider, DynamicResilienceStrategyProvider>();

            // 配置HTTP客户端
            ConfigureHttpClient(services);

            // 配置缓存
            ConfigureCaching(services);

            // 配置监控
            ConfigureMonitoring(services);

            // 注册后台服务
            services.AddHostedService<ServiceRegistrationHostedService>();
            services.AddHostedService<HeartbeatHostedService>();

            // 配置AutoMapper
            Configure<AbpAutoMapperOptions>(options =>
            {
                options.AddMaps<MatrixServiceCommunicationModule>();
            });
        }

        public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
        {
            var serviceProvider = context.ServiceProvider;

            // 启动后台任务
            var backgroundWorkerManager = serviceProvider.GetService<IBackgroundWorkerManager>();
            if (backgroundWorkerManager != null)
            {
                await backgroundWorkerManager.StartAsync();
            }

            // 自动注册当前服务实例
            await RegisterCurrentServiceAsync(serviceProvider);
        }

        private void ConfigureHttpClient(IServiceCollection services)
        {
            // 配置服务发现HTTP客户端
            services.AddHttpClient("Matrix.ServiceDiscovery", (serviceProvider, client) =>
            {
                var options = serviceProvider.GetRequiredService<IOptions<ServiceCommunicationOptions>>().Value;
                client.BaseAddress = new Uri(options.ServiceDiscovery.BaseUrl);
                client.Timeout = TimeSpan.FromSeconds(options.ServiceDiscovery.TimeoutSeconds);
            })
            .AddHttpMessageHandler(sp => new HttpClientLoggingHandler(sp.GetRequiredService<ILogger<HttpClientLoggingHandler>>()));

            // 配置服务通信HTTP客户端工厂
            services.AddHttpClient<IMatrixServiceClient>((serviceProvider, client) =>
            {
                var options = serviceProvider.GetRequiredService<IOptions<ServiceCommunicationOptions>>().Value;
                client.Timeout = TimeSpan.FromSeconds(options.DefaultTimeoutSeconds);
            })
            .AddHttpMessageHandler(sp => new HttpClientLoggingHandler(sp.GetRequiredService<ILogger<HttpClientLoggingHandler>>()))
            .AddHttpMessageHandler(sp => new HttpClientMetricsHandler(sp.GetRequiredService<IServiceCommunicationMetrics>()));
        }

        private void ConfigureCaching(IServiceCollection services)
        {
            services.AddDistributedMemoryCache();

            // 配置分布式缓存选项
            services.Configure<AbpDistributedCacheOptions>(options =>
            {
                options.KeyPrefix = "Matrix:ServiceCommunication";
            });
        }

        private void ConfigureMonitoring(IServiceCollection services)
        {
            // 配置监控相关服务
            services.AddTransient<HttpClientMetricsHandler>();
            services.AddTransient<HttpClientLoggingHandler>();
        }

        private async Task RegisterCurrentServiceAsync(IServiceProvider serviceProvider)
        {
            try
            {
                var options = serviceProvider.GetRequiredService<IOptions<ServiceCommunicationOptions>>().Value;
                var serviceDiscovery = serviceProvider.GetRequiredService<IServiceDiscoveryProvider>();
                var logger = serviceProvider.GetRequiredService<ILogger<MatrixServiceCommunicationModule>>();

                if (!options.ServiceRegistration.AutoRegister)
                {
                    logger.LogDebug("自动服务注册已禁用");
                    return;
                }

                var serviceInfo = options.ServiceRegistration;
                if (string.IsNullOrEmpty(serviceInfo.ServiceName))
                {
                    logger.LogWarning("服务名称未配置，跳过自动注册");
                    return;
                }

                var registerDto = new RegisterServiceDto
                {
                    ServiceName = serviceInfo.ServiceName,
                    InstanceId = serviceInfo.InstanceId ?? GenerateInstanceId(),
                    ServiceVersion = serviceInfo.ServiceVersion ?? "1.0.0",
                    Host = serviceInfo.Host ?? GetLocalHost(),
                    Port = serviceInfo.Port,
                    Protocol = serviceInfo.Protocol ?? "HTTP",
                    Weight = serviceInfo.Weight,
                    Metadata = serviceInfo.Metadata ?? new Dictionary<string, object>(),
                    Region = serviceInfo.Region,
                    Zone = serviceInfo.Zone,
                    Tags = serviceInfo.Tags ?? new List<string>(),
                    TtlSeconds = serviceInfo.TtlSeconds ?? 300 // 默认5分钟
                };

                await serviceDiscovery.RegisterServiceAsync(registerDto);
                logger.LogInformation("服务自动注册成功: {ServiceName}/{InstanceId}",
                    registerDto.ServiceName, registerDto.InstanceId);
            }
            catch (Exception ex)
            {
                var logger = serviceProvider.GetRequiredService<ILogger<MatrixServiceCommunicationModule>>();
                logger.LogError(ex, "服务自动注册失败");
            }
        }

        private static string GenerateInstanceId()
        {
            var machineName = Environment.MachineName ?? "unknown";
            var processId = Environment.ProcessId;
            var timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
            return $"{machineName}-{processId}-{timestamp}";
        }

        private static string GetLocalHost()
        {
            // 简化实现，获取本机IP
            return "localhost";
        }
    }

    /// <summary>
    /// 服务注册后台服务
    /// </summary>
    public class ServiceRegistrationHostedService : AsyncBackgroundWorkerBase
    {
        private readonly IServiceDiscoveryProvider _serviceDiscoveryProvider;
        private readonly IOptions<ServiceCommunicationOptions> _options;
        private readonly ILogger<ServiceRegistrationHostedService> _logger;

        public ServiceRegistrationHostedService(
            IServiceDiscoveryProvider serviceDiscoveryProvider,
            IOptions<ServiceCommunicationOptions> options,
            ILogger<ServiceRegistrationHostedService> logger)
            : base()
        {
            _serviceDiscoveryProvider = serviceDiscoveryProvider;
            _options = options;
            _logger = logger;
        }

        protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
        {
            try
            {
                var registration = _options.Value.ServiceRegistration;
                if (!registration.AutoRegister || string.IsNullOrEmpty(registration.ServiceName))
                {
                    return;
                }

                // 定期重新注册服务（防止注册丢失）
                var registerDto = new RegisterServiceDto
                {
                    ServiceName = registration.ServiceName,
                    InstanceId = registration.InstanceId ?? GenerateInstanceId(),
                    ServiceVersion = registration.ServiceVersion ?? "1.0.0",
                    Host = registration.Host ?? GetLocalHost(),
                    Port = registration.Port,
                    Protocol = registration.Protocol ?? "HTTP"
                };

                await _serviceDiscoveryProvider.RegisterServiceAsync(registerDto);
                _logger.LogDebug("服务重新注册: {ServiceName}", registration.ServiceName);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "服务重新注册失败");
            }
        }
    }

    /// <summary>
    /// 心跳后台服务
    /// </summary>
    public class HeartbeatHostedService : AsyncBackgroundWorkerBase
    {
        private readonly IServiceDiscoveryProvider _serviceDiscoveryProvider;
        private readonly IOptions<ServiceCommunicationOptions> _options;
        private readonly ILogger<HeartbeatHostedService> _logger;

        public HeartbeatHostedService(
            IServiceDiscoveryProvider serviceDiscoveryProvider,
            IOptions<ServiceCommunicationOptions> options,
            ILogger<HeartbeatHostedService> logger)
            : base()
        {
            _serviceDiscoveryProvider = serviceDiscoveryProvider;
            _options = options;
            _logger = logger;
        }

        protected override async Task DoWorkAsync(PeriodicBackgroundWorkerContext workerContext)
        {
            try
            {
                var registration = _options.Value.ServiceRegistration;
                if (!registration.AutoRegister || string.IsNullOrEmpty(registration.ServiceName))
                {
                    return;
                }

                // 发送心跳
                var heartbeatDto = new HeartbeatDto
                {
                    ServiceName = registration.ServiceName,
                    InstanceId = registration.InstanceId ?? GenerateInstanceId(),
                    Host = registration.Host ?? GetLocalHost(),
                    Port = registration.Port,
                    Timestamp = DateTime.UtcNow
                };

                await _serviceDiscoveryProvider.SendHeartbeatAsync(heartbeatDto);
                _logger.LogDebug("心跳发送成功: {ServiceName}/{InstanceId}",
                    heartbeatDto.ServiceName, heartbeatDto.InstanceId);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "心跳发送失败");
            }
        }
    }

    /// <summary>
    /// HTTP客户端日志处理器
    /// </summary>
    public class HttpClientLoggingHandler : DelegatingHandler
    {
        private readonly ILogger<HttpClientLoggingHandler> _logger;

        public HttpClientLoggingHandler(ILogger<HttpClientLoggingHandler> logger)
        {
            _logger = logger;
        }

        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var stopwatch = System.Diagnostics.Stopwatch.StartNew();

            _logger.LogDebug("发送HTTP请求: {Method} {Uri}", request.Method.Method, request.RequestUri);

            try
            {
                var response = await base.SendAsync(request, cancellationToken);
                stopwatch.Stop();

                _logger.LogDebug("HTTP请求完成: {Method} {Uri} -> {StatusCode} ({ElapsedMs}ms)",
                    request.Method.Method, request.RequestUri, response.StatusCode, stopwatch.ElapsedMilliseconds);

                return response;
            }
            catch (Exception ex)
            {
                stopwatch.Stop();
                _logger.LogError(ex, "HTTP请求失败: {Method} {Uri} ({ElapsedMs}ms)",
                    request.Method.Method, request.RequestUri, stopwatch.ElapsedMilliseconds);
                throw;
            }
        }
    }

    /// <summary>
    /// HTTP客户端指标处理器
    /// </summary>
    public class HttpClientMetricsHandler : DelegatingHandler
    {
        private readonly IServiceCommunicationMetrics _metrics;

        public HttpClientMetricsHandler(IServiceCommunicationMetrics metrics)
        {
            _metrics = metrics;
        }

        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var stopwatch = System.Diagnostics.Stopwatch.StartNew();

            try
            {
                var response = await base.SendAsync(request, cancellationToken);
                stopwatch.Stop();

                // 记录指标
                var serviceName = GetServiceNameFromRequest(request);
                if (!string.IsNullOrEmpty(serviceName))
                {
                    _metrics.RecordRequest(serviceName, request.Method.Method, (int)response.StatusCode, stopwatch.ElapsedMilliseconds, true);
                }

                return response;
            }
            catch (Exception)
            {
                stopwatch.Stop();

                var serviceName = GetServiceNameFromRequest(request);
                if (!string.IsNullOrEmpty(serviceName))
                {
                    _metrics.RecordRequest(serviceName, request.Method.Method, 500, stopwatch.ElapsedMilliseconds, false);
                }

                throw;
            }
        }

        private static string? GetServiceNameFromRequest(HttpRequestMessage request)
        {
            // 从请求头或请求URI中提取服务名称
            if (request.Headers.TryGetValues("X-Service-Name", out var serviceNames))
            {
                return serviceNames.FirstOrDefault();
            }

            // 从URI路径提取（简化实现）
            var path = request.RequestUri?.AbsolutePath;
            if (!string.IsNullOrEmpty(path) && path.StartsWith("/api/"))
            {
                var segments = path.Split('/', StringSplitOptions.RemoveEmptyEntries);
                if (segments.Length >= 2)
                {
                    return segments[1]; // 假设格式为 /api/{serviceName}/...
                }
            }

            return null;
        }
    }
}